package util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * Utility class to convert and format date and time.
 * 
 * @author jaslin.wee.2012, huiwensong.2012, sheryl.tay.2012, mohameds.2012,
 *         huangjm.2012
 * 
 */
public class DateUtil {

	public static final String MYSQL_DATE_PATTERN = "yyyy-MM-dd";
	public static final String MYSQL_TIME_PATTERN = "H:mm";

	public static final String INPUT_DATE_FORMAT = "yyyyMMdd";
	public static final String INPUT_DATE_REGEX = "\\d{8}";
	public static final String INPUT_TIME_FORMAT = "H:mm";
	public static final String INPUT_TIME_REGEX = "([1]?[0-9]|[2][0-3]):[0-5][0-9]";

	public static final String OUTPUT_DATE_PATTERN = "yyyyMMdd";
	public static final String OUTPUT_TIME_PATTERN = "Hmm";

	public static final int MON = 1;
	public static final int TUE = 2;
	public static final int WED = 3;
	public static final int THU = 4;
	public static final int FRI = 5;
	public static final int SAT = 6;
	public static final int SUN = 7;

	/**
	 * Combines the given date and time into one date object.
	 * 
	 * @param date
	 * @param time
	 * @return a date object combined from the given date and time
	 */
	public static Date combineDateAndTime(Date date, Date time) {
		if (date == null || time == null) {
			return null;
		}

		Calendar dateCal = Calendar.getInstance();
		dateCal.setTime(date);
		Calendar timeCal = Calendar.getInstance();
		timeCal.setTime(time);
		dateCal.set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY));
		dateCal.set(Calendar.MINUTE, timeCal.get(Calendar.MINUTE));
		dateCal.set(Calendar.SECOND, timeCal.get(Calendar.SECOND));
		dateCal.set(Calendar.MILLISECOND, timeCal.get(Calendar.MILLISECOND));
		return dateCal.getTime();
	}

	/**
	 * Parses date or time and converts it from String to Date type.
	 * 
	 * @param date
	 * @param pattern
	 * @return the date or time in Date type
	 * @throws IllegalArgumentException
	 *             if the given date string and the corresponding pattern
	 *             mismatch
	 */
	public static Date convertToDate(String date, String pattern) {
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(pattern);
			sdf.setLenient(false);
			return (Date) sdf.parse(date);
		} catch (ParseException e) {
			throw new IllegalArgumentException(date + " does not conform with "
					+ pattern);
		}
	}

	/**
	 * Formats date or time to the given pattern.
	 * 
	 * @param date
	 * @param pattern
	 * @return a formatted date or time String
	 */
	public static String formatDate(Date date, String pattern) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
		return simpleDateFormat.format(date);
	}

	/**
	 * Returns the day of week string in short form for the given day number.
	 * E.g. Mon, Tue, etc.
	 * 
	 * @param day
	 *            in number
	 * @return day of week in string
	 */
	public static String dayOfWeekShort(int day) {

		String dayOfWeekString = dayOfWeekLong(day);

		if (!dayOfWeekString.contains("invalid")) {
			dayOfWeekString = dayOfWeekString.substring(0, 3);
		}

		return dayOfWeekString;
	}

	/**
	 * Returns the day of week string in long form for the given day number.
	 * E.g. Monday, Tuesday, etc.
	 * 
	 * @param day
	 *            in number
	 * @return day of week in string
	 */
	public static String dayOfWeekLong(int day) {

		String dayOfWeekString = "";

		switch (day) {
		case MON:
			dayOfWeekString = "Monday";
			break;
		case TUE:
			dayOfWeekString = "Tuesday";
			break;
		case WED:
			dayOfWeekString = "Wednesday";
			break;
		case THU:
			dayOfWeekString = "Thursday";
			break;
		case FRI:
			dayOfWeekString = "Friday";
			break;
		case SAT:
			dayOfWeekString = "Saturday";
			break;
		case SUN:
			dayOfWeekString = "Sunday";
			break;
		default:
			dayOfWeekString = "invalid day";
			break;
		}

		return dayOfWeekString;
	}

	public static Date dateForThisWeek(int day) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.DAY_OF_WEEK, javaCalendarDayOfWeekFor(day));
		calendar.add(Calendar.WEEK_OF_MONTH, -1);
		
		return calendar.getTime();
	}

	private static int javaCalendarDayOfWeekFor(int day) {
		int javaCalendarDayOfWeekValue = -1;

		switch (day) {
		case MON:
			javaCalendarDayOfWeekValue = Calendar.MONDAY;
			break;
		case TUE:
			javaCalendarDayOfWeekValue = Calendar.TUESDAY;
			break;
		case WED:
			javaCalendarDayOfWeekValue = Calendar.WEDNESDAY;
			break;
		case THU:
			javaCalendarDayOfWeekValue = Calendar.THURSDAY;
			break;
		case FRI:
			javaCalendarDayOfWeekValue = Calendar.FRIDAY;
			break;
		case SAT:
			javaCalendarDayOfWeekValue = Calendar.SATURDAY;
			break;
		case SUN:
			javaCalendarDayOfWeekValue = Calendar.SUNDAY;
			break;
		}

		return javaCalendarDayOfWeekValue;
	}

	public static int getValueOfDateForField(Date date, int field) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(field);
	}

}
